using OpenTK.OpenGL;
using OpenTK.OpenGL.Enums;
using System.Drawing;
using OpenTK.Math;

namespace Dogfight2008.Common
{
  public class GLUtil
  {
    public static void Init()
    {
      //GL.ShadeModel(ShadingModel.Flat);
     // GL.Materialv(MaterialFace.Front, MaterialParameter.Diffuse, new float[] { 0, 0, 1, 1 });
      //GL.Materialv(MaterialFace.Front, MaterialParameter.Ambient, new float[] { 0, 0, 0.5f, 1 });
      //GL.Materialv(MaterialFace.Front, MaterialParameter.Emission, new float[] { 0, 0, 0, 1 });
      //GL.Materialv(MaterialFace.Front, MaterialParameter.Specular, new float[] { 0, 0, 0, 1 });
      GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
      SunLightDirection(1, 1, -1);
      GL.Lightv(LightName.Light0, LightParameter.Diffuse, new float[] { .8f, .8f, .8f, 1 });
      GL.Lightv(LightName.Light0, LightParameter.Ambient, new float[] { .5f, .5f, .5f, 1 });
      GL.Enable(EnableCap.Lighting);
      GL.Enable(EnableCap.Light0);
      GL.Enable(EnableCap.DepthTest);
      GL.Enable(EnableCap.ColorMaterial);
      GL.Enable(EnableCap.CullFace);
      GL.CullFace(CullFaceMode.Back);
      GL.ClearColor(Color.SkyBlue);
      GL.Enable(EnableCap.Normalize);
    }

    public static void SunLightDirection(double x, double y, double z)
    {
      GL.MatrixMode(MatrixMode.Modelview);
      GL.PushMatrix();
      GL.LoadIdentity();
      GL.Rotate(-90, Vector3.UnitX);
      GL.Lightv(LightName.Light0, LightParameter.Position,
        new float[] { (float)-x, (float)-y, (float)-z, 0 });
      GL.PopMatrix();
    }

    public static void DrawSoup(ColoredTriangleSoup soup)
    {
      GL.Begin(BeginMode.Triangles);
      foreach (ColoredTriangle tri in soup)
      {
        GL.Color3(tri.Color);
        GL.Normal3(tri.Triangle.Normal);
        GL.Vertex3(tri.Triangle.P1);
        GL.Vertex3(tri.Triangle.P2);
        GL.Vertex3(tri.Triangle.P3);
      }
      GL.End();
    }

    public static void DrawMesh(ColoredPolygonMesh mesh)
    {
      DrawMeshInternal(mesh, false);
    }

    private static void DrawMeshInternal(
      ColoredPolygonMesh mesh,
      bool ignorecolors)
    {
      foreach (ColoredPolygon polygon in mesh)
      {
        GL.Begin(BeginMode.Polygon);
        if(!ignorecolors)
          GL.Color3(polygon.Color);
        GL.Normal3(polygon.Normal);
        foreach (Vector3 v in polygon)
          GL.Vertex3(v);
        GL.End();
      }
    }


    public static void Clear()
    {
      GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
      GL.MatrixMode(MatrixMode.Modelview);
      GL.LoadIdentity();
      GL.Rotate(-90, Vector3.UnitX); // I want Z to be up, XY on ground ..
    }

    public static void DrawXYZAxis(double length)
    {
      GL.Disable(EnableCap.Lighting);
      GL.Disable(EnableCap.ColorMaterial);

      GL.Begin(BeginMode.Lines);

      // X
      GL.Color3(1.0, 0, 0);
      GL.Vertex3(0, 0, 0);
      GL.Vertex3(length, 0, 0);

      // Y
      GL.Color3(0, 1.0, 0);
      GL.Vertex3(0, 0, 0);
      GL.Vertex3(0, 100 * length, 0);

      // Z
      GL.Color3(0, 0, 1.0);
      GL.Vertex3(0, 0, 0);
      GL.Vertex3(0, 0, length);

      GL.End();

      GL.Enable(EnableCap.Lighting);
      GL.Enable(EnableCap.ColorMaterial);
    }

    public static void DrawMeshIgnoreColor(ColoredPolygonMesh coloredPolygonMesh)
    {
      DrawMeshInternal(coloredPolygonMesh, true);
    }
  }
}
